#include <WiFi.h>
#include <esp_now.h>

#include "WS_QMI8658.h"
#include "WS_Matrix.h"
#include "WS_Flow_S.h"

// English: Please note that the brightness of the lamp bead should not be too high, which can easily cause the temperature of the board to rise rapidly, thus damaging the board !!!
// Chinese: 请注意，灯珠亮度不要太高，容易导致板子温度急速上升，从而损坏板子!!!

extern IMUdata Accel;
IMUdata game;

// 新建队列句柄
QueueHandle_t dataQueue;
uint8_t flag = 1;

typedef struct {
  uint8_t type;
  float distance;
  float time;
  uint8_t data[8];
} data_fmt_t;

void setup() {
  // 初始化队列（队列长度可根据需求调整，这里设为10）
  dataQueue = xQueueCreate(10, sizeof(data_fmt_t));

  // 创建处理任务（优先级可根据需求调整，这里设为5）
  xTaskCreatePinnedToCore(
    dataProcessTask,
    "DataProcessTask",
    4096,
    NULL,
    5,
    NULL,
    APP_CPU_NUM);

  WiFi.mode(WIFI_AP);                    //开启热点，AP模式
  WiFi.softAP("Slave_Led", NULL, 6);     // 关键：使用相同信道，热点名字，如果需要添加密码，就WiFi.softAP("Slave_1"，密码)
  esp_now_init();                        //ESP now初始化
  esp_now_register_recv_cb(OnDataRecv);  //用于接受数据

  QMI8658_Init();
  Matrix_Init();
}

char font_data[8] = {0};

void loop() {
  led_color_handler();

  led_off_handler();

  led_red_handler();

  led_green_handler();

  led_blue_handler();

  led_game_handler();

  led_font_handler(font_data);
}

//回调函数
void OnDataRecv(const uint8_t* mac_addr, const uint8_t* data, int data_len) {
  data_fmt_t recvData;
  memcpy(&recvData, data, sizeof(data_fmt_t));

  // 将数据推入队列
  if (xQueueSend(dataQueue, &recvData, pdMS_TO_TICKS(100)) != pdPASS) {
    Serial.println("Queue full, data discarded!");
  }
}

// 新建数据处理任务
void dataProcessTask(void* pvParameter) {
  data_fmt_t taskData;

  while (1) {
    // 从队列中取出数据（阻塞等待）
    if (xQueueReceive(dataQueue, &taskData, portMAX_DELAY)) {
      // 原有数据处理逻辑
      if (taskData.type == 20) {
        flag = 1;
      } else if (taskData.type == 21) {
        flag = 2;
      } else if (taskData.type == 22) {
        flag = 3;
      } else if (taskData.type == 23) {
        flag = 4;
      } else if (taskData.type == 24) {
        flag = 5;
      } else if (taskData.type == 25) {
        flag = 6;
        RGB_Matrix1_Off();
      } else if (taskData.type == 26) {
        flag = 7;
        memcpy(font_data, taskData.data, 1);
        printf("data received:%s\n", font_data);
      } else {
        Serial.println("error data received!");
      }
    }
  }
}

int x_value = 0;
void led_color_handler(void) {
  if (flag == 1) {
    RGB_Matrix1(x_value);
    delay(100);
    x_value++;
    if (x_value == 24)
      x_value = 0;
  }
}

void led_off_handler(void) {
  if (flag == 2) {
    RGB_Matrix1_Off();
    delay(1000);
  }
}

void led_red_handler(void) {
  if (flag == 3) {
    RGB_Matrix1_Red();
    delay(1000);
  }
}

void led_green_handler(void) {
  if (flag == 4) {
    RGB_Matrix1_Green();
    delay(1000);
  }
}

void led_blue_handler(void) {
  if (flag == 5) {
    RGB_Matrix1_Blue();
    delay(1000);
  }
}

uint8_t X_EN = 0, Y_EN = 0, Time_X_A = 0, Time_X_B = 0, Time_Y_A = 0, Time_Y_B = 0;
void led_game_handler(void) {
  if (flag == 6) {
    QMI8658_Loop();
    if (Accel.x > 0.15 || Accel.x < 0 || Accel.y > 0.15 || Accel.y < 0 || Accel.z > -0.9 || Accel.z < -1.1) {
      if (Accel.x > 0.15) {
        Time_X_A = Time_X_A + Accel.x * 10;
        Time_X_B = 0;
      } else if (Accel.x < 0) {
        Time_X_B = Time_X_B + std::abs(Accel.x) * 10;
        Time_X_A = 0;
      } else {
        Time_X_A = 0;
        Time_X_B = 0;
      }
      if (Accel.y > 0.15) {
        Time_Y_A = Time_Y_A + Accel.y * 10;
        Time_Y_B = 0;
      } else if (Accel.y < 0) {
        Time_Y_B = Time_Y_B + std::abs(Accel.y) * 10;
        Time_Y_A = 0;
      } else {
        Time_Y_A = 0;
        Time_Y_B = 0;
      }
      if (Time_X_A >= 10) {
        X_EN = 1;
        Time_X_A = 0;
        Time_X_B = 0;
      }
      if (Time_X_B >= 10) {
        X_EN = 2;
        Time_X_A = 0;
        Time_X_B = 0;
      }
      if (Time_Y_A >= 10) {
        Y_EN = 2;
        Time_Y_A = 0;
        Time_Y_B = 0;
      }
      if (Time_Y_B >= 10) {
        Y_EN = 1;
        Time_Y_A = 0;
        Time_Y_B = 0;
      }
      Game(X_EN, Y_EN);
      X_EN = 0;
      Y_EN = 0;
    }
    delay(10);
  }
}

void led_font_handler(char* text) {
  if (flag == 7) {
    charFlow(text[0]);
    delay(100);
  }
}
